/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core.awt; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.io.*; import java.util.*; import javax.swing.JPanel; /** * A class that produces a page control component. * * <P> * <TABLE BORDER COLS=3 WIDTH=100%> * <TR><TH WIDTH=15%>Property<TH WIDTH=15%>Property Type<TH>Description * <TR><TD> Direction <TD> boolean <TD> Direction (upper or lower Pagecontrol) * <TR><TD> SelectedIndex <TD> int <TD> Index of selected tab. * </TABLE> * * @version 2.20, Jan 22, 1998 * @author Petr Hamernik, Ian Formanek */ public class PageControl extends Panel implements Serializable { /** generated Serialized Version UID */ static final long serialVersionUID = 4648659103970803518L; /** Width of the 3D border around the component */ protected final static int margin = 1; /** Vector of components inserted into PageControl. * @associates Component*/ protected Vector pages; /** TabControl component for switching among pages. */ protected TabControl tab; /** Previous dimension of the PageControl */ private Dimension dimLast = null; /** Vector of listeners which are invoked when the selction has changed. * @associates PropertyChangeListener*/ transient private Vector indexListeners = new Vector(); /** Focus listener for all components inserted in the PageControl. * When some component gains focus that it will be selected. */ private class PageFocusListener extends Object implements FocusListener { public void focusGained(FocusEvent e) { Component comp = e.getComponent(); int index = getIndexOfPage(comp); if (index != -1) setSelectedIndex(index); } public void focusLost(FocusEvent e) { } } /** Instance of focus listener */ PageFocusListener focusListener = new PageFocusListener(); /** Create new PageControl with all default values. */ public PageControl() { setLayout(new BorderLayout()); tab = new TabControl(); add(tab, "North"); // NOI18N validate(); pages = new Vector(); dimLast = new Dimension(0,0); // setBackground(SystemColor.control); // setForeground(SystemColor.controlText); tab.addIndexChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("selectedIndex")) { int oldSel = ((Integer) evt.getOldValue()).intValue(); int newSel = ((Integer) evt.getNewValue()).intValue(); for (int i = 0; i < tab.getTabCount(); i++) { if (i == newSel) ((Component) (pages.elementAt(i))).setVisible(true); else ((Component) (pages.elementAt(i))).setVisible(false); } fireIndexChange(oldSel, newSel); } } }); } /** Select new page. * @param index Index of new selected page. * @exception ArrayIndexOutOfBoundsException If the value was invalid. * @see #getSelectedIndex */ synchronized public void setSelectedIndex(int index) throws ArrayIndexOutOfBoundsException { int old = tab.getSelectedIndex(); if (old != index) { tab.setSelectedIndex(index); ((Component) (pages.elementAt(old))).setVisible(false); ((Component) (pages.elementAt(index))).setVisible(true); } fireIndexChange(old, index); } /** Gets the index of currently selected page. * @return Index of selected page. * @see #setSelectedIndex */ public int getSelectedIndex() { return tab.getSelectedIndex(); } /** Gets count of the pages. * @return Count of pages. */ public int getTabCount() { return tab.getTabCount(); } /** Gets the name of the page with the specific index. * @param index Index of page. * @exception ArrayIndexOutOfBoundsException If the value was invalid. * @return Name of page. */ public String getTabLabel(int index) throws ArrayIndexOutOfBoundsException { return tab.getTabLabel(index); } /** Add new page. * @param newTab Name of new page. * @param comp Component which will be inserted into PageControl. */ synchronized public void addPage(String newTab, Component comp) { int index = tab.getTabCount(); addPageAt(newTab, comp, index); } /** Add new page at specific position. * @param newTab Name of new page. * @param comp Component which will be inserted into PageControl. * @param index Position of new page. * @exception ArrayIndexOutOfBoundsException If the value was invalid. */ synchronized public void addPageAt(String newTab, Component comp, int index) throws ArrayIndexOutOfBoundsException { pages.insertElementAt(comp, index); add(comp, "Center"); // NOI18N tab.addTabAt(newTab, index); validate(); countSizes(); int j = getSelectedIndex(); if (j == -1) { setSelectedIndex(index); j = index; } for (int i = 0; i < tab.getTabCount(); i++) { if (i != j) ((Component) pages.elementAt(i)).setVisible(false); else ((Component) pages.elementAt(i)).setVisible(true); } registerListeners(comp); } /** Gets index of page. * @param comp searching component * @return index or -1 if component is not inserted into PageControl */ synchronized public int getIndexOfPage(Component comp) { for (int i = 0; i < tab.getTabCount(); i++) { if (comp.equals(pages.elementAt(i))) return i; } return -1; } /** Gets the component of specific page. * @param index Position of page. * @exception ArrayIndexOutOfBoundsException If the value was invalid. */ public Component getPageAt(int index) throws ArrayIndexOutOfBoundsException { return (Component) pages.elementAt(index); } /** Removes the page at the specific position. * @param index Position of page. * @exception ArrayIndexOutOfBoundsException If the value was invalid. */ synchronized public void removePageAt(int index) throws ArrayIndexOutOfBoundsException { boolean b = false; if (index == tab.getSelectedIndex()) b = true; Component comp = (Component) pages.elementAt(index); remove(comp); unregisterListeners(comp); pages.removeElementAt(index); tab.removeTabAt(index); if (b) { int i = getSelectedIndex(); if (i != -1) ((Component) (pages.elementAt(i))).setVisible(true); } repaint(); } /** Remove all pages. * @see #removePageAt */ synchronized public void removeAllPages() { tab.removeAllTabs(); for (int i = 0; i < pages.size(); i++) { Component comp = (Component) pages.elementAt(i); remove(comp); unregisterListeners(comp); } pages.removeAllElements(); repaint(); } /** Sets a new direction of PageControl. If it is true, * TabControl if on the top of PageControl otherwise * at the bottom. * @param direct New direction. * @see #getDirection */ public void setDirection(boolean direct) { if (tab.getDirection() != direct) { tab.setDirection (direct); remove(tab); if (tab.getDirection()) add(tab,"North"); // NOI18N else add(tab,"South"); // NOI18N countSizes(); repaint(); } } /** Gets the current direction of PageControl. If it is true, * TabControl if on the top of PageControl otherwise * at the bottom. * @return Current direction. * @see #setDirection */ public boolean getDirection() { return tab.getDirection(); } private void countSizes() { Dimension d = tab.getPreferredSize(); Dimension t = getSize(); dimLast = t; Dimension ts = tab.getSize(); if (ts != d) tab.setSize(t.width, d.height); Component comp; int x,y; if (tab.getDirection()) { if ((tab.getLocation().x != 0) || (tab.getLocation().y != 0)) tab.setLocation(0,0); x = margin; y = d.height; } else { if ((tab.getLocation().x != 0) || (tab.getLocation().y != (t.height - d.height))) tab.setLocation(0, t.height - d.height); x = margin; y = margin; } int w = t.width - 2 * margin; int h = t.height - d.height - 2 * margin; for (int i = 0; i < getTabCount(); i++) { comp = (Component) pages.elementAt(i); comp.setBounds(x, y, w, h); comp.validate(); } } public void paint(Graphics g) { Dimension s = getSize(); if (s != dimLast) countSizes(); if (tab.getTabCount() > 0) { int left = 0; int width = s.width - 1; int height = s.height - tab.getSize().height + margin - 1; int top = 0; if (tab.getDirection()) top = tab.getSize().height - margin; g.setColor(SystemColor.controlHighlight); for(int i = 0; i < margin; i++) { g.draw3DRect(left, top, width, height, true); left++; top++; width = width - 2; height = height - 2; } } else { g.setColor(getBackground()); g.fillRect(0, 0, s.width, s.height); } } public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); countSizes(); } public void setSize(int width, int height) { super.setSize(width, height); countSizes(); } public void setSize(Dimension d) { super.setSize(d); countSizes(); } public Dimension getMinimumSize() { return countSize(true); } public Dimension getPreferredSize() { return countSize(false); } private Dimension countSize(boolean min_pref) { Dimension d = (min_pref ? tab.getMinimumSize() : tab.getPreferredSize()); Dimension e = new Dimension(0, 0); for (int i = 0; i < tab.getTabCount(); i++) { Component p = (Component) pages.elementAt(i); Dimension f = (min_pref ? p.getMinimumSize() : p.getPreferredSize()); if (e.width < f.width) e.width = f.width; if (e.height < f.height) e.height = f.height; } return new Dimension(Math.max(d.width, e.width), d.height + e.height); } public void addIndexChangeListener(PropertyChangeListener l) { indexListeners.addElement(l); } public void removeIndexChangeListener(PropertyChangeListener l) { indexListeners.removeElement(l); } protected void fireIndexChange(int oldValue, int newValue) { Vector newListeners = (Vector)indexListeners.clone(); Enumeration en = newListeners.elements(); PropertyChangeEvent evt = new PropertyChangeEvent(this, "selectedIndex", // NOI18N new Integer(oldValue), new Integer(newValue)); while (en.hasMoreElements()) ((PropertyChangeListener) en.nextElement()).propertyChange(evt); } /** Register as focus listener at the added component */ private void registerListeners(Component comp) { comp.addFocusListener(focusListener); } /** Unregister as focus listener from the removed component */ private void unregisterListeners(Component comp) { comp.removeFocusListener(focusListener); } private void writeObject (ObjectOutputStream os) throws IOException{ os.writeObject (pages); os.writeObject (tab); os.writeObject (dimLast); } private void readObject (ObjectInputStream is) throws IOException { try { pages = (Vector) is.readObject (); tab = (TabControl) is.readObject (); dimLast = (Dimension) is.readObject (); } catch (ClassNotFoundException ex) { throw new IOException (ex.toString()); } indexListeners = new Vector(); setBackground(SystemColor.control); setForeground(SystemColor.controlText); tab.addIndexChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("selectedIndex")) { int oldSel = ((Integer) evt.getOldValue()).intValue(); int newSel = ((Integer) evt.getNewValue()).intValue(); for (int i = 0; i < tab.getTabCount(); i++) { if (i == newSel) ((Component) (pages.elementAt(i))).setVisible(true); else ((Component) (pages.elementAt(i))).setVisible(false); } fireIndexChange(oldSel, newSel); } } }); } } /* * Log * 4 src-jtulach1.3 1/12/00 Ales Novak i18n * 3 src-jtulach1.2 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 2 src-jtulach1.1 4/16/99 Libor Martinek * 1 src-jtulach1.0 3/9/99 Jaroslav Tulach * $ * Beta Change History: * 0 Tuborg 2.08 --/--/98 Jan Formanek reflecting access rights changes in TabControl * 0 Tuborg 2.10 --/--/98 Petr Hamernik focusListeners added * 0 Tuborg 2.12 --/--/98 Petr Hamernik changes in index listeners * 0 Tuborg 2.13 --/--/98 Ales Novak serializable * 0 Tuborg 2.20 --/--/98 Jan Formanek made lightweight (tried, not succeeded) * 0 Tuborg 2.20 --/--/98 Jan Formanek background color not set anymore */